from django.shortcuts import render
from django.views import View
from meiduo_mall.utils.views import LoginRequiredMixinJSONMixin
from django_redis import get_redis_connection
from apps.goods.models import SKU
from decimal import Decimal
from django import http

# Create your views here.


class OrderSettlementView(LoginRequiredMixinJSONMixin, View):
    def get(self, request):
        """结算订单逻辑实现"""
        # 查询当前登录用户未被逻辑删除的地址
        address_model_list = request.user.addresses.filter(is_deleted=False)

        # 查询redis购物车中未被勾选的商品信息
        user_id = request.user.id
        redis_conn = get_redis_connection('carts')
        redis_cart = redis_conn.hgetall('carts_%s' % user_id)
        redis_selected = redis_conn.smembers("selected_%s" % user_id)

        new_cart = {}
        for sku_id in redis_selected:
            new_cart[int(sku_id)] = int(redis_cart[sku_id])

        # 将地址模型列表转字典列表
        addresses = []
        for address in address_model_list:
            addresses.append({
                "id": address.id,
                "province": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "receiver": address.receiver,
                "mobile": address.mobile,
            })

        # 将购物车商品列表转字典列表
        sku_ids = new_cart.keys()
        sku_model_list = SKU.objects.filter(id__in=sku_ids)
        skus = []
        for sku in sku_model_list:
            skus.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'count': new_cart[sku_id],
                "price": sku.price,
            })

        # 指定邮费
        # 邮费是金钱，对于钱的精度必须非常高的，所以金钱的定义不能直接使用简单的float
        # python提供了定义金钱的类型 Decimal
        freight = Decimal(11.1)

        # 构造响应数据
        context = {
            'addresses': addresses,
            'skus': skus,
            'freight': freight,
        }

        # 响应结果
        return http.JsonResponse({"code": 0, 'errmsg': 'OK', 'context': context})


class OrderCommitView(LoginRequiredMixinJSONMixin, View):
    """订单提交"""
    def post(self, request):
        """保存订单信息和商品信息"""
        # 接收参数
        # 校验参数
        # 判断支付方式是否在固定范围内(由商城限制和支持的)
        # 在操作订单相关的数据表时,显式的开启一次事务,使用上下文
            # 操作数据之前,创建事务保存点,用来记录数据操作前的初始状态,方便回滚还原事务
        # 生成订单号,order_id = '年月日是分秒'+'9位用户id'
        # strftime('时间格式'):时间对象转时间字符串.时间格式<====>%Y%m%d%H%M%S
        # 保存订单基本信息 OrderInfo（一）
        # 订单状态和支付方式绑定:支付宝<-->待支付;货到付款<-->待发货
        # 从redis读取购物车中被勾选的商品信息
        # 遍历购物车中被勾选的商品信息
        # 提交订单时,查询商品绝不能使用filter(id__in=sku_ids)
        # 因为filter返回查询集,而查询集有缓存;但是,提交订单数据时是实时更新库存和销量的,此时库存和销量不能为缓存数据
        # 查询SKU信息
        # 获取原始库存和销量:作为乐观锁标记,标记数据操作前的初始状态
        # 判断SKU库存:是否满足购买量
        # 购买量大于库存量-->回滚事务还原数据并返回库存不足
        # 购买量小于库存量
        # 模拟并发下单的错误,放大网络延迟,
            # SKU减少库存，增加销量
            # 计算新库存和新销量
            # 使用乐观锁操作SKU减少库存,增加销量
            # update()返回值是影响行数.若发现资源竞争,则不执行update
                # 有资源竞争,重新下单,直到库存不足
                # 注意:下单操作是在一个死循环中进行的
            # 修改SPU销量
            # 保存订单商品信息 OrderGoods（多）
            # 保存商品订单中总价和总数量
            # 总数量
            # 总金额
            # 购买成功,跳出死循环
        # 添加邮费和保存订单信息:邮费只累计一次,要放在循环外
        # 订单相关数据表操作都成功,则显式提交一次事务(同步数据到Mysql数据库)
        # 实付款
        # 清除购物车中已结算的商品
        # 响应提交订单结果
        pass